﻿using System.Data.Linq;
using System.Linq;

namespace Storage.EntityModels
{
    using Exceptions;

    #region Trip
    
    /// <summary>
    /// This class represents the Trips table into entities model.
    /// </summary>
    public partial class Trip
    {       
        #region AddStage

        /// <summary>
        /// Adds a new Stage to this Trip.
        /// It also modifies the Ordinal values of other Stages.
        /// <example>
        /// The Trip 
        /// 
        /// Trip {
        ///   Id = 0,
        ///   Stage {
        ///     Ordinal = 1,
        ///     ... 
        ///   }, 
        ///   Stage {
        ///     Ordinal = 2,
        ///     ...
        ///   },
        ///   Stage {
        ///     Ordinal = 3.
        ///     ...
        ///   }
        /// }
        /// 
        /// becomes with a new Stage with Ordinal = 2:
        /// 
        /// Trip {
        ///   Id = 0,
        ///   Stage {
        ///     Ordinal = 1,
        ///     ...
        ///   },
        ///   Stage {
        ///     Ordinal = 2, // The new Stage!
        ///     ...
        ///   },
        ///   Stage {
        ///     Ordinal = 3,
        ///     ...
        ///   },
        ///   Stage {
        ///     Ordinal = 4,
        ///     ...
        ///   }
        /// }
        /// </example>
        /// </summary>
        /// <param name="s">The new Stage.</param>
        public void AddStage(Stage s)
        {
            TripLoaDataContext db = StorageManager.Instance.Entities;
            //db.Trip_insertStage(Id, s.Ordinal);
            //db.Refresh(RefreshMode.KeepChanges, Stages);

            foreach (Stage existinStage in Stages) 
            {
                if (existinStage.Ordinal >= s.Ordinal) 
                    existinStage.Ordinal++;
            }

            Stages.Add(s);
        }

        #region RemoveStage
        
        /// <summary>
        /// Removes a Stage from a trip.
        /// </summary>
        /// <param name="ordinal">The ordinal of the Stage to remove.</param>
        public void RemoveStage(int ordinal)
        {
            TripLoaDataContext db = StorageManager.Instance.Entities;
            
            // Elimino lo stage desiderato.
            db.Stages.
                DeleteOnSubmit(Stages.First(s => s.Ordinal == ordinal));

            // Aggiorno il campo Ordinal dei rimanenti Stage.
            Stages
                .Where(s => s.Ordinal > ordinal)
                .ForEach(s => s.Ordinal--);
        } 

        #endregion

        #endregion

        #region Partial methods: OnValidate

        partial void OnValidate(ChangeAction action)
        {
#if DEBUG
            // una volta che un viaggio è stato completato e i suoi dati sono stati inseriti...
            // è possibile modificarli!? perchè in questo caso dopo la prima volta che in update
            // Accomplished è messo a true allora non può + essere modificato nulla

            if (action == ChangeAction.Insert || action == ChangeAction.Update)
            {
                if (_Draft)
                {
                    if (_Accomplished)
                        throw new TripValidationException("A trip cannot be Draft and Accomplished at the same time!");

                    if (_RealBudget.HasValue)
                        throw new TripValidationException("A trip that is a draft cannot have a RealBudget associated!");

                    if (_RealTime.HasValue)
                        throw new TripValidationException("A trip that is a draft cannot have a RealTime associated!");
                }
                else if (!_Accomplished)
                {
                    if (_RealBudget.HasValue)
                        throw new TripValidationException("A trip that is not accomplished cannot have a RealBudget associated!");

                    if (_RealTime.HasValue)
                        throw new TripValidationException("A trip that is not accomplished cannot have a RealTime associated!");

                    // TODO: .. add more constraints.
                }

                if (action == ChangeAction.Update && Accomplished)
                    throw new TripValidationException("An accomplished Trip cannot be changed!");
            }
#endif
        } 

        #endregion
    } 

    #endregion
}
